/*
 * Copyright 2018, 2019, 2020, 2021 Dooboolab.
 *
 * This file is part of Flutter-Sound.
 *
 * Flutter-Sound is free software: you can redistribute it and/or modify
 * it under the terms of the Mozilla Public License version 2 (MPL2.0),
 * as published by the Mozilla organization.
 *
 * Flutter-Sound is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * MPL General Public License for more details.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

import 'dart:async';
import 'dart:io';
import 'package:audio_session/audio_session.dart';
import 'package:digital/https/apiUrl.dart';
import 'package:digital/https/http.dart';
import 'package:digital/provider/user_provider.dart';
import 'package:dio/dio.dart';
// import 'package:fijkplayer/fijkplayer.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:flutter_tts/flutter_tts.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
import 'package:video_player/video_player.dart';

import '../common/utils/toast.dart';
import '../router/router_utils.dart';
import 'msg/model/testEntity.dart';
import 'msg/view/tts.dart';

/*
 * This is an example showing how to record to a Dart Stream.
 * It writes all the recorded data from a Stream to a File, which is completely stupid:
 * if an App wants to record something to a File, it must not use Streams.
 *
 * The real interest of recording to a Stream is for example to feed a
 * Speech-to-Text engine, or for processing the Live data in Dart in real time.
 *
 */

///
typedef _Fn = void Function();

/// Example app.
class RecordToStreamExample extends StatefulWidget {
  const RecordToStreamExample({super.key});

  @override
  State<RecordToStreamExample> createState() => _RecordToStreamExampleState();
}

class _RecordToStreamExampleState extends State<RecordToStreamExample> {
  FlutterSoundPlayer? _mPlayer = FlutterSoundPlayer();
  FlutterSoundRecorder? _mRecorder = FlutterSoundRecorder();
  bool _mPlayerIsInited = false;
  bool _mRecorderIsInited = true;
  int sampleRate = 16000;
  // int sampleRate = 44100;

  /// 更新状态，默认为 true，表示录音器已初始化
  // bool _isProcessing = true; // 更新状态，默认为 true，表示正在录音
  String? _mPath;
  Dio _dio = Dio();
  bool _mplaybackReady = false;
  StreamSubscription? _mRecordingDataSubscription;

  List<ChatMessage> messagesList = [];

  // 文字转语音
  late FlutterTts flutterTts;
  String? language;
  String? engine;
  double volume = 0.5;
  double pitch = 1.0;
  double rate = 0.5;
  bool isCurrentLanguageInstalled = false;
  bool get isAndroid => !kIsWeb && Platform.isAndroid;

  TtsState ttsState = TtsState.stopped;

  // 新增
  var arguments = RouterUtils.getArgument();

  bool isCall = false; //是否拨打期间
  // bool videoIsPlay = false; //视频是否播放
  bool isDispose = false; //是否返回页面
  // final FijkPlayer player = FijkPlayer();
  bool textWord = false;
  VideoPlayerController? _videoPlayerController;

  /// 文字转语音
  dynamic initTts() {
    flutterTts = FlutterTts();

    _setAwaitOptions();

    if (isAndroid) {
      _getDefaultEngine();
      _getDefaultVoice();
    }

    flutterTts.setStartHandler(() {
      setState(() {
        print("Playing");
        ttsState = TtsState.playing;
      });
    });

    flutterTts.setCompletionHandler(() {
      setState(() {
        print("Complete");
        ttsState = TtsState.stopped;
      });
    });

    flutterTts.setCancelHandler(() {
      setState(() {
        print("Cancel");
        ttsState = TtsState.stopped;
      });
    });

    flutterTts.setPauseHandler(() {
      setState(() {
        print("Paused");
        ttsState = TtsState.paused;
      });
    });

    flutterTts.setContinueHandler(() {
      setState(() {
        print("Continued");
        ttsState = TtsState.continued;
      });
    });

    flutterTts.setErrorHandler((msg) {
      setState(() {
        print("error: $msg");
        ttsState = TtsState.stopped;
      });
    });
  }

  Future<void> _speak(String _newVoiceText) async {
    await flutterTts.setVolume(volume);
    await flutterTts.setSpeechRate(rate);
    await flutterTts.setPitch(pitch);
    await flutterTts.speak(_newVoiceText);
  }

  Future<void> _setAwaitOptions() async {
    await flutterTts.awaitSpeakCompletion(true);
  }

  Future<void> _getDefaultEngine() async {
    var engine = await flutterTts.getDefaultEngine;
    if (engine != null) {
      print(engine);
    }
  }

  Future<void> _getDefaultVoice() async {
    var voice = await flutterTts.getDefaultVoice;
    if (voice != null) {
      print(voice);
    }
  }

  Future<void> init() async {
    print("imagePath====${arguments["imagePath"]}");
    try {
      _videoPlayerController =
          VideoPlayerController.network(arguments["imagePath"])
            ..initialize().then((_) {
              _videoPlayerController!.play();
              setState(() {
                isCall = true;
              });
            });

      // _videoPlayerController!.addListener(() {
      //   if (_videoPlayerController!.value.position ==
      //       _videoPlayerController!.value.duration) {
      //     _videoPlayerController!
      //         .seekTo(Duration.zero); // Seek to the start of the video
      //     _videoPlayerController!.play(); // Continue playing
      //   }
      // });
    } on Exception catch (e) {
      print('rtmp初始化失败: $e');
    }
  }

  Future<void> _openRecorder() async {
    var status = await Permission.microphone.request();
    if (status != PermissionStatus.granted) {
      throw RecordingPermissionException('Microphone permission not granted');
    }
    await _mRecorder!.openRecorder();
    final session = await AudioSession.instance;
    await session.configure(AudioSessionConfiguration(
      avAudioSessionCategory: AVAudioSessionCategory.playAndRecord,
      avAudioSessionCategoryOptions:
          AVAudioSessionCategoryOptions.allowBluetooth |
              AVAudioSessionCategoryOptions.defaultToSpeaker,
      avAudioSessionMode: AVAudioSessionMode.spokenAudio,
      avAudioSessionRouteSharingPolicy:
          AVAudioSessionRouteSharingPolicy.defaultPolicy,
      avAudioSessionSetActiveOptions: AVAudioSessionSetActiveOptions.none,
      androidAudioAttributes: const AndroidAudioAttributes(
        contentType: AndroidAudioContentType.speech,
        flags: AndroidAudioFlags.none,
        usage: AndroidAudioUsage.voiceCommunication,
      ),
      androidAudioFocusGainType: AndroidAudioFocusGainType.gain,
      androidWillPauseWhenDucked: true,
    ));
    //sampleRate = await _mRecorder!.getSampleRate();

    setState(() {
      _mRecorderIsInited = true;
    });
  }

  Future<void> initRecorder() async {
    await init();
    await _openRecorder();
    await record();
    await initTts();
  }

  @override
  void initState() {
    super.initState();
    // Be careful : openAudioSession return a Future.
    // Do not access your FlutterSoundPlayer or FlutterSoundRecorder before the completion of the Future
    _mPlayer!.openPlayer().then((value) {
      setState(() {
        _mPlayerIsInited = true;
      });
    });
    initRecorder();
  }

  @override
  void dispose() {
    isDispose = true;
    // player.release();

    _videoPlayerController?.dispose(); //视频播放

    stopPlayer();
    _mPlayer!.closePlayer();
    _mPlayer = null;

    stopRecorder();
    _mRecorder!.closeRecorder();
    _mRecorder = null;

    flutterTts.stop();
    super.dispose();
  }

  Future<IOSink> createFile() async {
    var tempDir = await getTemporaryDirectory();
    final dateTime = DateTime.now().millisecondsSinceEpoch;
    _mPath = '${tempDir.path}/temp_talk_$dateTime.pcm';
    var outputFile = File(_mPath!);
    if (outputFile.existsSync()) {
      await outputFile.delete();
    }
    return outputFile.openWrite();
  }

  // ----------------------  Here is the code to record to a Stream ------------

  Timer? _silenceTimer;
  final _recorderController = StreamController<RecordingDisposition>();
  double silenceThreshold = -40; // 阈值设为-40dB，根据需要调整

  Future<void> record() async {
    assert(_mRecorderIsInited && _mPlayer!.isStopped);
    var sink = await createFile();
    var recordingDataController = StreamController<Uint8List>();
    _mRecordingDataSubscription =
        recordingDataController.stream.listen((buffer) {
      sink.add(buffer);
    });
    await _mRecorder!.startRecorder(
      toStream: recordingDataController.sink,
      codec: Codec.pcm16,
      numChannels: 1,
      bitRate: 16,
      sampleRate: sampleRate,
      bufferSize: 8192,
      enableVoiceProcessing: true,
    );
    setState(() {});

    _mRecorder!.onProgress!.listen((RecordingDisposition disposition) {
      print("decibels============${disposition.decibels}");
      updateRecorderProgress(duration: 100, dbPeakLevel: disposition.decibels);
    });
  }

  Future<void> stopRecorder() async {
    await _mRecorder!.stopRecorder();
    // 停止监听
    _silenceTimer?.cancel();
    _silenceTimer = null;
    if (_mRecordingDataSubscription != null) {
      await _mRecordingDataSubscription!.cancel();
      _mRecordingDataSubscription = null;
    }
    _mplaybackReady = true;
    if (!isDispose) {
      stopRecorderFn();
    }
  }

  void updateRecorderProgress({int? duration, double? dbPeakLevel}) {
    _recorderController.add(RecordingDisposition(
      Duration(milliseconds: duration!),
      dbPeakLevel,
    ));
    print("dbPeakLevel: $dbPeakLevel");

    if (dbPeakLevel != null && dbPeakLevel < silenceThreshold) {
      // 如果声音分贝低于阈值，启动计时器
      _silenceTimer?.cancel(); // 取消之前的计时器
      _silenceTimer = Timer(const Duration(seconds: 5), () {
        stopRecorder(); // 5秒后停止录音
      });
    } else {
      // 如果声音分贝高于阈值，重置计时器
      _silenceTimer?.cancel();
      _silenceTimer = null;
    }
  }

  Future<void> stopRecorderFn() async {
    await getTextFn();
  }

  // Future<void> uploadFn(String file) async {
  //   print("file=======${file}");
  //   EasyLoading.show();
  //   var res = await ApiClient().postFromRequest(apiUrl.uploadsApi,
  //       data: {"file": await MultipartFile.fromFile(file)});
  //   EasyLoading.dismiss();
  //   print(res);
  // }

  // --------------------- (it was very simple, wasn't it ?) -------------------

  getTextFn() async {
    print("_mPath在getTextFn=======${_mPath}");
    var response = await ApiClient().postFromRequest("${apiUrl.uploadVoiceApi}",
        data: {"file": await MultipartFile.fromFile(_mPath!)});

    // Map<String, dynamic> response = {
    //   "code": "0",
    //   "data": {
    //     "transcription":
    //         "我认为跑步最重要的就是给我带来了身体健康${DateTime.now().millisecondsSinceEpoch.toString()}",
    //     "answer": "你好啊${DateTime.now().millisecondsSinceEpoch.toString()}",
    //   },
    //   "error_msg": ""
    // };
    if (response["code"] == "0") {
      AnswerData answerData = AnswerData.fromJson(response["data"]);
      ChatMessage objTranscription =
          ChatMessage(message: answerData.transcription ?? "");
      ChatMessage objAnswer = ChatMessage(message: answerData.answer ?? "");
      setState(() {
        textWord = true;
        messagesList.add(objTranscription);
        messagesList.add(objAnswer);

        // 打开录音
        _mRecorderIsInited = true;
      });
      // await Future.delayed(const Duration(seconds: 1));
      // await player.setDataSource(url, autoPlay: true);
      _speak(objAnswer.message);
      await _openRecorder();
      await record();
      return;
    } else if (response["code"] == "2000") {
      Toast.showToast("处理中，请等待...");
      return;
    } else {
      // 其他出错处理
      Toast.showToast("Server Internal Error");
      return;
    }
  }

  _Fn? getRecorderFn() {
    if (!_mRecorderIsInited || !_mPlayer!.isStopped) {
      return null;
    }
    return _mRecorder!.isStopped
        ? record
        : () {
            stopRecorder().then((value) => setState(() {}));
          };
  }

  // pcmToWaveFn() async {
  //   var tempDir = await getTemporaryDirectory();
  //   var path = '${tempDir.path}/flutter_sound_YHXD.wav';
  //   print("_mPath前=====$_mPath");
  //   await flutterSoundHelper.pcmToWave(
  //     inputFile: _mPath!,
  //     outputFile: path, // 使用相同的文件路径，覆盖原有的 .pcm 文件
  //     numChannels: 1,
  //     sampleRate: 16000,
  //   );
  //   _mPath = path;
  // }

  void play() async {
    assert(_mPlayerIsInited &&
        _mplaybackReady &&
        _mRecorder!.isStopped &&
        _mPlayer!.isStopped);
    await _mPlayer!.startPlayer(
        fromURI: _mPath,
        sampleRate: sampleRate,
        codec: Codec.pcm16,
        numChannels: 1,
        whenFinished: () {
          setState(() {});
        }); // The readability of Dart is very special :-(
    setState(() {});
  }

  Future<void> stopPlayer() async {
    await _mPlayer!.stopPlayer();
  }

  _Fn? getPlaybackFn() {
    if (!_mPlayerIsInited || !_mplaybackReady || !_mRecorder!.isStopped) {
      return null;
    }
    return _mPlayer!.isStopped
        ? play
        : () {
            stopPlayer().then((value) => setState(() {}));
          };
  }

  // ----------------------------------------------------------------------------------------------------------------------
  @override
  Widget build(BuildContext context) {
    final height = MediaQuery.of(context).size.height;
    final width = MediaQuery.of(context).size.width;
    return Scaffold(
      body: Consumer<UserProvider>(
        builder: (context, vm, _) {
          return Stack(
            fit: StackFit.expand,
            children: [
              // 使用图片作为背景
              Positioned.fill(
                bottom: 0,
                child: Container(
                  height: height, // 调整图片高度以适应不同设备
                  width: width,
                  decoration: const BoxDecoration(
                    image: DecorationImage(
                      image: AssetImage(
                          'assets/images/teacher/bg.png'), // 替换为你的图片路径
                      fit: BoxFit.cover,
                    ),
                  ),
                ),
              ),

              // 底部图片
              !isCall
                  ? Positioned(
                      bottom: 0, // 将图片放在底部
                      left: 0,
                      right: 0,
                      child: Container(
                        alignment: Alignment.center, // 居中对齐
                        child: Image.asset(
                          'assets/images/index_bg.png', // 底部图片的路径
                          fit: BoxFit.cover,
                          width: width, // 使图片宽度与屏幕宽度相同
                        ),
                      ),
                    )
                  : Positioned.fill(
                      bottom: 0,
                      left: 0,
                      right: 0,
                      child: _videoPlayerController!.value.isInitialized
                          ? AspectRatio(
                              aspectRatio:
                                  _videoPlayerController!.value.aspectRatio,
                              child: VideoPlayer(_videoPlayerController!),
                            )
                          : Container()),

              // Positioned(
              //     bottom: 0, // 将图片放在底部
              //     left: 0,
              //     right: 0,
              //     child: Container(
              //       alignment: Alignment.center, // 居中对齐
              //       // child: Image.network(
              //       //   arguments['imagePath'], // 底部图片的路径
              //       //   fit: BoxFit.cover,
              //       //   width: 280, // 使图片宽度与屏幕宽度相同
              //       //   height: 590, // 使图片宽度与屏幕宽度相同
              //       // ),
              //       child: Image.asset(
              //         'assets/images/index_bg.png', // 底部图片的路径
              //         fit: BoxFit.cover,
              //         width: 280, // 使图片宽度与屏幕宽度相同
              //         height: 590, // 使图片宽度与屏幕宽度相同
              //       ),
              //     ),
              //   )

              // Positioned.fill(
              //     bottom: 0,
              //     child: FijkView(
              //       height: height, // 调整图片高度以适应不同设备
              //       width: width,
              //       player: player,
              //     )),

              // 半透明遮罩层
              Positioned.fill(
                child: Container(
                  height: height, // 调整图片高度以适应不同设备
                  width: width,
                  color: Colors.black.withOpacity(0.4), // 设置遮罩层的颜色和透明度
                ),
              ),

              isCall
                  ? Positioned(
                      top: 48,
                      left: 20,
                      child: GestureDetector(
                          onTap: () {
                            RouterUtils.back(context);
                          },
                          child: Image.asset(
                              "assets/images/icon_back_white.png",
                              fit: BoxFit.cover,
                              width: 24.w)),
                    )
                  : Container(),

              isCall
                  ? textWord
                      ? Positioned(
                          bottom: 142.h, // 从顶部偏移
                          left: 0,
                          right: 0, // 添加这一行以实现水平居中
                          child: _msgList(messagesList),
                        )
                      : Container()
                  : Positioned(
                      bottom: 200.h, // 从顶部偏移
                      left: 0,
                      right: 0, // 添加这一行以实现水平居中
                      child: Container(
                        padding: EdgeInsets.symmetric(horizontal: 16.w),
                        child: Column(
                          children: [
                            Text(
                              arguments['label'],
                              textAlign: TextAlign.center,
                              style: const TextStyle(
                                  fontSize: 20, color: Colors.white),
                            ),
                            const SizedBox(height: 16),
                            const Text(
                              "正在呼叫中...",
                              textAlign: TextAlign.center,
                              style:
                                  TextStyle(fontSize: 14, color: Colors.white),
                            ),
                          ],
                        ),
                      ),
                    ),

              Positioned(
                bottom: 80.h, // 从顶部偏移
                left: 0,
                right: 0,
                child: isCall
                    ? Row(children: [
                        const Spacer(),
                        ElevatedButton(
                            style: ButtonStyle(
                              backgroundColor: MaterialStateProperty.all<Color>(
                                  Colors.transparent), // 设置背景透明
                              padding:
                                  MaterialStateProperty.all<EdgeInsetsGeometry>(
                                      EdgeInsets.zero), // 取消内边距
                            ),
                            onPressed: getRecorderFn(),
                            child: Container(
                                alignment: Alignment.center,
                                child: Image.asset(
                                  _mRecorder!.isRecording
                                      ? "assets/images/startVoice.png"
                                      : "assets/images/stopVoice.png",
                                  fit: BoxFit.cover,
                                  width: 56.w,
                                  height: 56.w,
                                ))),
                        const Spacer(),
                      ])
                    : GestureDetector(
                        onTap: () {
                          RouterUtils.back(context);
                        },
                        child: Container(
                            alignment: Alignment.center,
                            child: Image.asset("assets/images/cancelCall.png",
                                fit: BoxFit.cover, width: 56.w))),
              ),

              isCall
                  ? Positioned(
                      bottom: 50.h,
                      left: 0,
                      right: 0,
                      child: Text(
                        _mRecorder!.isRecording ? '停止说话' : '点击说话',
                        textAlign: TextAlign.center,
                        style: TextStyle(fontSize: 14, color: Colors.white),
                      ),
                    )
                  : Container(),
            ],
          );
        },
      ),
    );
  }

  Widget _msgList(List<ChatMessage> messagesList) {
    return Container(
      constraints: const BoxConstraints(maxHeight: 400), // 限制最大高度为400
      padding: const EdgeInsets.symmetric(vertical: 9),
      child: SingleChildScrollView(
        scrollDirection: Axis.vertical,
        child: ListView.builder(
          shrinkWrap: true, // 添加 shrinkWrap，让 ListView 自适应内容高度
          physics: const NeverScrollableScrollPhysics(),
          itemCount: messagesList.length,
          itemBuilder: (context, index) {
            ChatMessage item = messagesList[index];
            return Container(
              margin: const EdgeInsets.symmetric(horizontal: 30, vertical: 8),
              padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
              decoration: BoxDecoration(
                color: Colors.white.withOpacity(0.5),
                borderRadius: BorderRadius.circular(6),
              ),
              child: Text(
                item.message,
                textAlign: TextAlign.center,
                style: const TextStyle(fontSize: 14, color: Colors.white),
              ),
            );
          },
        ),
      ),
    );
  }
}
